package com.seguriapp.alerts.gwt.client.activity;

import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import net.customware.gwt.dispatch.client.DispatchAsync;

import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.seguriapp.alerts.gwt.client.place.AlertDetailsPlace;
import com.seguriapp.alerts.gwt.shared.GetAlertsDataAction;
import com.seguriapp.alerts.gwt.shared.GetAlertsDataResult;
import com.seguriapp.common.gwt.client.AbstractSeguriAppActivity;
import com.seguriapp.common.gwt.client.AbstractSeguriAppPlace;
import com.seguriapp.common.gwt.client.SeguriAppCallback;
import com.seguriapp.common.gwt.client.SeguriAppClientSession;
import com.seguriapp.common.gwt.client.SeguriAppDisplay;
import com.seguriapp.common.gwt.client.pagination.PageChangedEvent;
import com.seguriapp.common.gwt.client.pagination.PageChangedEventHandler;
import com.seguriapp.common.gwt.client.pagination.SearchPagination;
import com.seguriapp.common.gwt.client.pagination.SearchPaginationPresenter;
import com.seguriapp.common.gwt.client.searchfilter.SearchFilter;
import com.seguriapp.common.gwt.client.searchfilter.SearchFilterAppliedEvent;
import com.seguriapp.common.gwt.client.searchfilter.SearchFilterAppliedEventHandler;
import com.seguriapp.common.gwt.client.searchfilter.SearchFilterPresenter;
import com.seguriapp.complaints.gwt.shared.GetPoliceStationListAction;
import com.seguriapp.complaints.gwt.shared.GetPoliceStationListResult;
import com.seguriapp.entities.Alert;
import com.seguriapp.entities.SeguriAppEntity;
import com.seguriapp.gwt.client.login.AlertReadEvent;
import com.seguriapp.gwt.client.login.AlertReceivedEvent;
import com.seguriapp.gwt.client.login.AlertReceivedEventHandler;

public class AlertsListActivity extends AbstractSeguriAppActivity {

  static final Logger logger = Logger.getLogger(AlertsListActivity.class.getName());

  private final Display display;
  private List<Alert> alertsList;
  private Date startDate;
  private Date endDate;
  private String names;
  private double latitude;
  private double longitude;
  private long page;
  private boolean ascending;
  private String columnSort;
  private int distance;
  private long policeStationId;
  private boolean searchByPolStation;

  public AlertsListActivity(final DispatchAsync dispatchAsync, final EventBus eventBus, final PlaceController placeController, final Display display,
      final AbstractSeguriAppPlace place, final SeguriAppClientSession clientSession) {
    super(dispatchAsync, eventBus, placeController, place, clientSession);
    display.setPresenter(this);
    this.display = display;
  }

  public void setStartDate(final Date startDate) {
    this.startDate = startDate;
  }

  public void setEndDate(final Date endDate) {
    this.endDate = endDate;
  }

  public void setNames(final String names) {
    this.names = names;
  }

  public void setLatitude(final double latitude) {
    this.latitude = latitude;
  }

  public void setLongitude(final double longitude) {
    this.longitude = longitude;
  }

  public void setDistance(final int distance) {
    this.distance = distance;
  }

  public void setPoliceStationId(final long policeStationId) {
    this.policeStationId = policeStationId;
  }

  public void setSearchByPolStation(final boolean searchByPolStation) {
    this.searchByPolStation = searchByPolStation;
  }

  public void setPage(final long page) {
    this.page = page;
  }

  public void setAscending(final boolean ascending) {
    this.ascending = ascending;
  }

  public void setColumnSort(final String columnSort) {
    this.columnSort = columnSort;
  }

  @Override
  protected void onStart(final AcceptsOneWidget widget, final EventBus eventBus) {
    widget.setWidget(display.asWidget());
    setPage(FIRST_PAGE);
    updateAlertsList();
    initializeSearchFilters();
    addNewAlertsEventHandlers();
  }

  private void addNewAlertsEventHandlers() {
    eventBus.fireEvent(new AlertReadEvent());
    showNewAlertSign(0);
    eventBus.addHandler(AlertReceivedEvent.TYPE, new AlertReceivedEventHandler() {

      public void onNewAlert(final AlertReceivedEvent event) {
        showNewAlertSign(event.getAlertsCount());
      }

    });
  }

  private void showNewAlertSign(final int alertsCount) {
    display.showNewAlertsLink(alertsCount);
  }

  private void initializeSearchFilters() {
    getPoliceStationListFromServer();
    new SearchPaginationPresenter(eventBus, display.getPagination()).start();
    eventBus.addHandler(PageChangedEvent.TYPE, new PageChangedEventHandler() {

      public void onPageChanged(PageChangedEvent event) {
        setPage(event.getPage());
        updateAlertsList();
      }
    });
  }

  private void getPoliceStationListFromServer() {
    final GetPoliceStationListAction action = new GetPoliceStationListAction();
    action.setSearch(true);
    dispatchAsync.execute(action, new SeguriAppCallback<GetPoliceStationListResult>() {

      public void onSuccess(final GetPoliceStationListResult result) {
        initializeSearchFilters(result.getPoliceStationList());
      }

      public void onFailure(Throwable e) {
        initializeSearchFilters(null);
      }
    });
  }

  private void initializeSearchFilters(final List<SeguriAppEntity> policeStationList) {
    new SearchFilterPresenter(eventBus, display.getSearchFilter(), policeStationList).start();
    eventBus.addHandler(SearchFilterAppliedEvent.TYPE, new SearchFilterAppliedEventHandler() {

      public void onSearchFilterApplied(final SearchFilterAppliedEvent event) {
        searchAlerts(event.getStartDate(), event.getEndDate(), event.getNames(), event.getLatitude(), event.getLongitude(), event.getDistance(),
            event.getPoliceStationId(), event.isSearchByPolStation());
      }

    });
  }

  private void searchAlerts(final Date startDate, final Date endDate, final String names, final double latitude, final double longitude,
      final int distance, final long policeStationId, final boolean searchByPolStation) {
    setStartDate(startDate);
    setEndDate(endDate);
    setNames(names);
    setLatitude(latitude);
    setLongitude(longitude);
    setDistance(distance);
    setPoliceStationId(policeStationId);
    setSearchByPolStation(searchByPolStation);
    setPage(FIRST_PAGE);
    updateAlertsList();
  }

  public void updateAlertsList() {
    final GetAlertsDataAction action = new GetAlertsDataAction();
    action.setPage(page);
    action.setEndDate(endDate);
    action.setLatitude(latitude);
    action.setLongitude(longitude);
    action.setNames(names);
    action.setStartDate(startDate);
    action.setAscending(ascending);
    action.setColumnSort(columnSort);
    action.setDistance(distance);
    action.setPoliceStationId(policeStationId);
    action.setSearchByPolStation(searchByPolStation);
    dispatchAsync.execute(action, new SeguriAppCallback<GetAlertsDataResult>() {

      public void onSuccess(final GetAlertsDataResult result) {
        alertsList = result.getAlertList();
        if (alertsList != null && !alertsList.isEmpty()) {
          display.setGridData(alertsList);
          display.setPagination(result.getCurrentPage(), result.getTotalPages(), result.getMaxPages());
        } else {
          display.showNoDataMessage();
        }
      }

      public void onFailure(final Throwable e) {
        Window.alert("Error: " + e.getMessage());
      }
    });

  }

  public void goToAlertDetailsPage(final Alert alert) {
    clientSession.put(SeguriAppClientSession.Key.Alert, alert, true);
    final Place place = new AlertDetailsPlace("");
    placeController.goTo(place);
  }

  public void showNewAlerts() {
    eventBus.fireEvent(new AlertReadEvent());
    setStartDate(null);
    setEndDate(null);
    setNames(null);
    setLatitude(0);
    setLongitude(0);
    setDistance(0);
    setPoliceStationId(0);
    setSearchByPolStation(false);
    setPage(FIRST_PAGE);
    updateAlertsList();
  }

  public interface Display extends SeguriAppDisplay {

    void setPresenter(AlertsListActivity presenter);

    void showNewAlertsLink(int alertsCount);

    void setPagination(long currentPage, long totalPages, long maxPages);

    void showNoDataMessage();

    SearchFilter getSearchFilter();

    SearchPagination getPagination();

    void setGridData(List<Alert> alertsList);

  }

}
